<?php
/*
 * add by menghao
 * 模型管理类
 */
class model
{
    
    public $table;
    public $table_field;
    private $db;
    public $error;

    public function __construct()
    {
        global $db;
        $this->table = DB_PRE.'model';
        $this->table_field = DB_PRE.'model_field';
        $this->db = $db;
    }

    /**
     * 添加模型
     * @author menghao
     * @param <array> $data
     * @return <boolean>
     */
    function add($data)
    {
        if(!$this->db->insert($this->table, $data))
        {
            $this->error = "添加模型失败";
            return false;
        }
        $modelid = $this->db->uuid();
        $tablename = $data['tablename'];
        if(!$this->addtable($tablename))
        {
            $this->error = "创建数据表 $tablename 失败";
        }
        $this->add_system_field($modelid);
        $this->cache_model($modelid);
        return true;
    }

    /**
     * 为模型添加默认的系统字段
     * @author menghao
     * @param <int> $modelid
     * @return <boolean>
     */
    function add_system_field($modelid)
    {
        $setting['title'] = serialize(array('size'=>50,'minlength'=>3,'maxlength'=>200));
        $setting['thumb'] = serialize(array('size'=>50,'maxlength'=>200));
        $setting['link'] = serialize(array('size'=>50,'maxlength'=>200));

        //标题
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'title',
            'name'      => '标题',
            'tips'      => '',
            'formtype'  => 'title',
            'settings'  => $setting['title'],
            'length'    => 200,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 1,
            'showlist'  => 1,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);

        //缩略图
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'thumb',
            'name'      => '缩略图',
            'tips'      => '',
            'formtype'  => 'thumb',
            'settings'  => $setting['thumb'],
            'length'    => 100,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 1,
            'showlist'  => 0,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);
        
        //转向链接
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'link',
            'name'      => '转向链接',
            'tips'      => '',
            'formtype'  => 'link',
            'settings'  => $setting['link'],
            'length'    => 200,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 1,
            'showlist'  => 0,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);

        //发布日期
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'addtime',
            'name'      => '发布日期',
            'tips'      => '',
            'formtype'  => 'addtime',
            'settings'  => '',
            'length'    => 1,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 1,
            'showlist'  => 0,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);
        
        //推荐到
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'commend',
            'name'      => '推荐到',
            'tips'      => '',
            'formtype'  => 'commend',
            'settings'  => '',
            'length'    => 50,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 1,
            'showlist'  => 0,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);
        
        //推荐到
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'school',
            'name'      => '学校列表',
            'tips'      => '',
            'formtype'  => 'schools',
            'settings'  => '',
            'length'    => 40,
            'default'   => '',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 0,
            'isempty'   => 0,
            'showedit'  => 1,
            'showlist'  => 1,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);
        

        //状态
        $field_config = array(
            'modelid'   => $modelid,
            'field'     => 'status',
            'name'      => '状态',
            'tips'      => '',
            'formtype'  => 'status',
            'settings'  => '',
            'length'    => 1,
            'default'   => '1',
            'regex'     => '',
            'issystem'  => 1,
            'isunique'  => 1,
            'isempty'   => 1,
            'showedit'  => 0,
            'showlist'  => 0,
            'showpage'  => 1,
            'disabled'  => 0,
            'listorder' => 0,
        );
        $this->db->insert($this->table_field, $field_config);
        return true;
    }

    /**
     * 检查数据唯一性
     * @author menghao
     * @param <string> $table
     * @param <string> $key
     * @param <string> $value
     * @return <boolean>
     */
    function check_unique($table, $key, $value, $condition='')
    {
        $sql = "select * from `$table` where status=? and $key=? ";
        if(!empty($condition))
        {
            $sql .= " and $condition";
        }
        $this->db->prepare($sql);
        $this->db->set_int(STATUS_NORMAL);
        $this->db->set_string($value);
        $result = $this->db->execute();

        if(!empty($result)) return false;
        return true;
    }

    /**
     * 添加模型附加表
     * @author menghao
     * @param <string> $tablename
     * @return <boolean>
     */
    function addtable($tablename)
    {
        $tablename = DB_PRE.'c_'.$tablename;
        return $this->db->query("CREATE TABLE `$tablename` (`contentid` char(36) NOT NULL) DEFAULT CHARSET=utf8");
    }

    /**
     * 删除模型
     * @author menghao
     * @param <int> $id
     * @return <boolean>
     */
    function delete($id)
    {
        $data = $this->getone($id);
        $tablename = DB_PRE.'c_'.$data['tablename'];
        if(!$this->db->query("drop TABLE IF EXISTS `$tablename`"))
        {
            $this->error = '删除数据表失败';
            return false;
        }
        if(!$this->db->fake_delete($this->table, array('id'=>$id)))
        {
            $this->error = '删除模型失败';
            return false;
        }
        return $this->db->fake_delete($this->table_field, array('modelid' => $id));
    }

    /**
     * 获取一条模型数据
     * @author menghao
     * @param <int> $id
     * @return <array>
     */
    function getone($id)
    {
        return $this->db->get_one($this->table, $id);
    }

    /**
     * 更新模型信息
     * @author menghao
     * @param <int> $id
     * @param <array> $data
     * @return <boolean>
     */
    function update($id, $data)
    {
        $result = $this->db->simple_update($this->table, $data, array('id'=>$id));
        $this->cache_model($id);
        return $result;
    }

    /**
     * 获取全部模型数据
     * @author menghao
     * @return <boolean>
     */
    function listinfo()
    {
        $result = $this->db->query("select * from $this->table where status=".STATUS_NORMAL." order by id desc");
        if(is_array($result))
        {
            foreach($result as &$r)
            {
                $tables = $this->db->query("show TABLE STATUS where name = '".DB_PRE."c_{$r['tablename']}'");
                $tb = array_shift(&$tables);
                $datacount = isset($tb['Rows']) ? $tb['Rows'] : 0;
                $r['datacount'] = $datacount;
            }
        }
        return $result;
    }

    /**
     * 获取模型下属所有字段
     * @author menghao
     * @param <type> $modelid
     * @return <array>
     */
    function listfield($modelid, $condition='')
    {
        $this->db->prepare("select * from $this->table_field where status=? and modelid=? $condition order by listorder desc,id asc");
        $this->db->set_int(STATUS_NORMAL);
        $this->db->set_string($modelid);
        return $this->db->execute();
    }

    /**
     * 获取一条字段的数据
     * @author menghao
     * @param <int> $id
     * @return <array>
     */
    function get_field($id)
    {
        return $this->db->get_one($this->table_field, $id);
    }

    /**
     * 添加模型字段
     * @author menghao
     * @param <type> $data
     * @return <boolean>
     */
    function field_add($data)
    {
        $data['length'] = intval($data['length']);
        $data['isempty'] = intval($data['isempty']);
        
        $model = $this->getone($data['modelid']);
        $modeltable = DB_PRE.'c_'.$model['tablename'];

        $isempty = $data['isempty'] ? '' : 'NOT NULL';
        $default = "default '{$data['default']}'";
        $formtype = $data['formtype'];
        include_once APP_ROOT."include/fields/$formtype.class.php";
        $fieldclass = "field_$formtype";
        $field = new $fieldclass;
        $type = $field->field_type;
        
        if(!$this->db->insert($this->table_field, $data))
        {
            $this->error = "添加数据失败";
            return false;
        }
        if($data['issystem']==0)
        {
            $text = array('MEDIUMTEXT','TEXT','LONGTEXT');
            $alter_sql = in_array($type,$text) ? "ALTER TABLE $modeltable ADD {$data['field']} $type $isempty $default" : "ALTER TABLE $modeltable ADD {$data['field']} $type({$data['length']}) $isempty $default";
	        if(!$this->db->query($alter_sql))
	        {
	            $this->error = "添加字段失败";
	            return false;
	        }
        }
        $this->cache_model($data['modelid']);
        return true;
    }

    function field_check($data)
    {
        $errors = array();
        if(!isset($data['field']) || empty($data['field']))
        {
            array_push(&$errors, array('inputid'=>'field','msg'=>"字段名不能为空"));
        }
        elseif(strlen($data['field'])>20)
        {
            array_push(&$errors, array('inputid'=>'field','msg'=>"字段名不能超过20个字节"));
        }
        elseif(!preg_match('/^[a-z]{1}[a-z0-9]*$/i', $data['field']))
        {
            array_push(&$errors, array('inputid'=>'field','msg'=>"字段名只能由小写字母和数字组成，且第一位为小写字母"));
        }
        
        if(!isset($data['name']) || empty($data['name']))
        {
            array_push(&$errors, array('inputid'=>'name','msg'=>"字段别名不能为空"));
        }
        elseif(strlen($data['name'])>30)
        {
            array_push(&$errors, array('inputid'=>'name','msg'=>"字段别名不能超过30个字节"));
        }

        if(strlen($data['tips'])>60000)
        {
            array_push(&$errors, array('inputid'=>'tips','msg'=>"字段提示不能超过60000个字节"));
        }
        if(strlen($data['regex'])>50)
        {
            array_push(&$errors, array('inputid'=>'regex','msg'=>"数据校验正则不能超过50个字节"));
        }
        return $errors;
    }

    /**
     * 删除模型字段
     * @author menghao
     * @param <int> $id
     * @return <boolean>
     */
    function field_delete($id)
    {
        $field = $this->get_field($id);
        $model = $this->getone($field['modelid']);
        $modeltable = DB_PRE.'c_'.$model['tablename'];

        if(!$this->db->fake_delete($this->table_field, array('id'=>$id)))
        {
            $this->error = '删除字段失败';
            return false;
        }
        if(!$this->db->query("ALTER TABLE $modeltable DROP COLUMN {$field['field']}"))
        {
            $this->error = "删除字段失败";
            return false;
        }
        $this->cache_model($field['modelid']);
        return true;
    }

    /**
     * 禁止/启用该字段
     * @author menghao
     * @param <int> $id
     * @param <int> $status
     * @return <boolean>
     */
    function field_status($id, $status)
    {
        $status = intval($status);
        $field = $this->get_field($id);

        $action = $status == 0 ? '启用' : '禁止';
        $result = $this->db->simple_update($this->table_field, array('disabled'=>$status), array('id'=>$id));
        $this->cache_model($field['modelid']);
        if(empty($result))
        {
            $this->error = "$action 操作失败";
            return false;
        }
        return true;
    }

    /**
     * 更新模型字段
     * @author menghao
     * @param <int> $id
     * @param <array> $data
     * @return <boolean>
     */
    function field_update($id, $data)
    {
        if(isset($data['length'])) 
        {
            $data['length'] = intval($data['length']);
        }
        if(isset($data['isempty']))
        {
            $data['isempty'] = intval($data['isempty']);
        }

        $model = $this->getone($data['modelid']);
        $modeltable = DB_PRE.'c_'.$model['tablename'];

        if(isset($data['isempty']))
        {
            $isempty = $data['isempty'] ? '' : 'NOT NULL';
        }
        if(isset($data['default']))
        {
            $default = "default '{$data['default']}'";
        }
        $formtype = $data['formtype'];
        include_once APP_ROOT."include/fields/$formtype.class.php";
        $fieldclass = "field_$formtype";
        $field_obj = new $fieldclass;
        $type = $field_obj->field_type;
        
        $result = $this->db->simple_update($this->table_field, $data, array('id'=>$id));
        $this->cache_model($data['modelid']);
        if(empty($result))
        {
            $this->error = "修改数据失败";
            return false;
        }
        if(!$data['issystem'])
        {
            if(!$this->db->query("ALTER TABLE $modeltable MODIFY {$data['field']} $type({$data['length']}) $isempty $default"))
            {
                $this->error = "修改字段失败";
                return false;
            }
        }
        return true;
    }

    /**
     * 模型字段排序
     * @author menghao
     * @param <array> $listorder
     * @return <boolean>
     */
    function field_listorder($modelid, $listorder)
    {
        if(is_array($listorder))
        {
            foreach($listorder as $i=>$v)
            {
                $v = intval($v);
                $this->db->query("update $this->table_field set listorder=$v where id='$i'");
            }
        }
        $this->cache_model($modelid);
        return true;
    }

    /**
     * 缓存模型
     * @author menghao
     * @param <int> $modelid
     * @return <boolean>
     */
    function cache_model($modelid)
    {
        $model = $this->getone($modelid);
        $fields = $this->listfield($modelid, ' and disabled=0');
        if(is_array($fields))
        {
            foreach($fields as $f)
            {
                $f['settings'] = unserialize($f['settings']);
                $model['fields'][$f['field']] = $f;
            }
        }
        cache_write('model_'.$modelid, $model);
        return true;
    }

    /**
	 * 获得所有模型ID、模型名称
	 *
	 * @param 空
	 * @return array $list
	 */
    public function get_all_model()
    {
        $model = $this->listinfo();
		$model_list = array();
		if(is_array($model))
		{
			foreach ($model as $m)
			{
				$model_list[$m['id']] = $m['name'];
			}
		}
    	return $model_list;
    }

    public function get_all_fields()
    {
        $field_dir = APP_ROOT . 'include/fields';
        get_file_list($field_dir, $files);
        $fields = array();
        foreach($files as $file)
        {
            $filename = basename($file);
            if(preg_match('/^(\w+).class.php$/i', $filename, $matches))
            {
                include_once $file;
                $field_id = $matches[1];
                $classname = 'field_'.$field_id;
                if(!class_exists($classname))
                {
                    continue;
                }
                $obj = new $classname;
                $field_name = $obj->fieldname();
                $fields[$field_id] = $field_name;
            }
            
        }
        return $fields;
    }
}
?>
